import _ from 'lodash'

// Function

// 节流  _.throttle(func, [wait=0], [options={}])
const throttledFunction = _.throttle(() => {
    console.log("throttle");
}, 1000);

// 源码
function throttle(func, wait, options) {
    var leading = true,
        trailing = true;
    if(typeof func != 'function') {
        throw new TypeError("Expected a function");
    }
    if(_.isObject(options)) {
        leading = 'leading' in options ? !!options.leading : leading;
        trailing = 'trailing' in options ? !!options.trailing : trailing;
    }
    return debounce(func, wait, {
        'leading': leading,
        'maxWait': wait,
        'trailing': trailing
    })
}

// 防抖 _.debounce(func, [wait=0], [options={}])
const debounceFunction = _.debounce(() => {
    console.log("debounce");
}, 1000)

// 源码
function debounce(func, wait, options) {
    var lastArgs,
        lastThis,
        maxWait,
        result,
        timerId,
        lastCallTime,
        lastInvokeTime = 0,
        leading = false,
        maxing = false,
        trailing = true;
    if (typeof func != 'function') {
        throw new TypeError('Expected a function');
    }
    wait = _.toNumber(wait) || 0;
    if(_.isObject(options)) {
        leading = !!options.leading;
        maxing = 'maxWait' in options;
        // maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
        trailing = 'trailing' in options ? !!options.trailing : trailing;
    }

    function invokeFunc(time) {
        var args = lastArgs,
            thisArg = lastThis;
        lastArgs = lastThis = undefined;
        lastInvokeTime = time;
        result = func.apply(thisArg, args);
        return result;
    }

    function leadingEdge(time) {
        // Reset any `maxWait` timer.
        lastInvokeTime = time;
        // Start the timer for the trailing edge.
        timerId = setTimeout(timerExpired, wait);
        // Invoke the leading edge.
        return leading ? invokeFunc(time) : result;
    }

    function remainingWait(time) {
        var timeSinceLastCall = time - lastCallTime,
            timeSinceLastInvoke = time - lastInvokeTime,
            timeWaiting = wait - timeSinceLastCall;

        return maxing
            ? Math.min(timeWaiting, maxWait - timeSinceLastInvoke)
            : timeWaiting;
    }


}

export {
    throttledFunction,
    debounceFunction
}
